﻿<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8"/>
<title>Пересечение отрезков</title>
<link rel="stylesheet" type="text/css" href="../lib/styles.css"/>
<script type="text/javascript" src="../lib/jquery-1.7.2.min.js"></script>
<script type="text/javascript" src="../lib/raphael-min.js"></script>
<script type="text/javascript">
	$(function(){
		var paper = new Raphael($("#paper1")[0]);
		var ptSize = 5;
		var segments = [
			[[100, 100], [200, 200]],
			[[150, 100], [120, 200]]
		];
		
		Raphael.fn.segment = function(segIdx, color){
			var p1 = segments[segIdx][0], p2 = segments[segIdx][1];
			var sgmt = paper.path(["M", p1.join(), "L", p2.join()]).attr({stroke:color}),
				ptAttr = {fill:color, "stroke-width":0, cursor:"move"},
				pt1 = paper.circle(p1[0], p1[1], ptSize, ptSize).attr(ptAttr)
					.drag(dragmove, dragstart, dragend)
					.data({ptIdx:0, segment: sgmt, segIdx: segIdx}),
				pt2 = paper.circle(p2[0], p2[1], ptSize, ptSize).attr(ptAttr)
					.drag(dragmove, dragstart, dragend)
					.data({ptIdx:1, segment: sgmt, segIdx: segIdx});
				
				function dragstart(x, y, e) {
					this.data("current_transform", this.transform());
				}
				function dragmove(dx, dy, x, y, e) {
					this.transform(this.data("current_transform")+'T'+dx+','+dy);
					var sgmt = this.data("segment"),
						ptIdx = this.data("ptIdx"),
						segIdx = this.data("segIdx");
					var path = sgmt.attr("path");
					var bbox = this.getBBox();
					
					path[ptIdx][1] = segments[segIdx][ptIdx][0] = (bbox.x+bbox.x2)/2;
					path[ptIdx][2] = segments[segIdx][ptIdx][1] = (bbox.y+bbox.y2)/2;
					sgmt.attr("path", path);
					
					var intersection = getIntersection();
					if(intersection)
						intersectionPt.show().attr({cx:intersection.x, cy:intersection.y});
					else
						intersectionPt.hide();
					
				}
				function dragend(e) {
					this.data("current_transform", this.transform());
				}
			
			return paper.set(sgmt, pt1, pt2);
		};
		
		function getIntersection(){
			var segm1 = segments[0], segm2 = segments[1];
			if(segm1[0][0]==segm1[1][0]) return verticalIntersection(1, segm1[0][0], segm1[0][1], segm1[1][1]);
			if(segm2[0][0]==segm2[1][0]) return verticalIntersection(0, segm2[0][0], segm2[0][1], segm2[1][1]);
				
			var f1 = getSegmFunc(0), f2 = getSegmFunc(1);
			/***********************************
				y = f1(x) = f2(x)
				a1*x+b1 = a2*x+b2
				x(a1-a2) = b2-b1
				x = (b2-b1)/(a1-a2)
			************************************/
			var dF = f1.a - f2.a;
			if(!dF) dF = 1e-9; //exclude division by Zero
			var x = (f2.b - f1.b)/dF,
				y = f1.a*x + f1.b;
			
			if(
				between(x, segm1[0][0], segm1[1][0]) &&
				between(x, segm2[0][0], segm2[1][0]) &&
				between(y, segm1[0][1], segm1[1][1]) &&
				between(y, segm2[0][1], segm2[1][1])
			)
				return {x: x, y: y};
			else
				return null;
		}
			
		function verticalIntersection(segmIdx, x, y1, y2){
			var segm = segments[segmIdx];
			if(!between(x, segm[0][0], segm[1][0])) return;
			var f = getSegmFunc(segmIdx);
			var y = f.a*x + f.b;
			if(between(y, y1, y2)) return {x:x, y:y};
		}
		
		function between(x, a, b){
			var arr = [a, x, b];
			arr = arr.sort(function(x1,x2){return x1==x2?0:x1<x2?-1:1;});
			return arr[1]===x;
		}
		
		function getSegmFunc(segIdx){
			var sgmt = segments[segIdx],
				p1 = sgmt[0], p2 = sgmt[1];
			/**********************************************
				y = ax+b
				p1[1] = a*p1[0]+b
				p2[1] = a*p2[0]+b
				b = p1[1] - a*p1[0] = p2[1] - a*p2[0]
				a*(p2[0] - p1[0]) = p2[1] - p1[1]
				a = (p2[1] - p1[1])/(p2[0] - p1[0])
			***********************************************/
			var dP = p2[0] - p1[0];
			if(!dP) dP = 1e-9; // exclude division by Zero
			var a = (p2[1] - p1[1])/dP;
			return {a: a, b: p1[1] - a*p1[0]};
		}
		
		paper.segment(0, "#008");
		paper.segment(1, "#080");
		
		var intersection = getIntersection();
		var intersectionPt = paper.circle(intersection.x, intersection.y, ptSize, ptSize).attr({fill:"#f00", "stroke-width":0});
	});
</script>
</head>
<body>
	<h1>Пересечение отрезков</h1>
	<p>Указания: отрезки можно перемещать за концы, при этом отображается точка их пересечения.</p>

	<div id="paper1" class="paper" style="width:600px; height:400px;">
	</div>
	
	<h2>Литература</h2>
	<ol>
		<li><a href="http://raphaeljs.com/reference.html#Raphael.angle">Raphael Reference - Raphael.angle</a></li>
	</ol>
</body>
</hmtl>